<template>
  <div
    class="common-tree-wrap"
    :style="{
      '--theme-color': systemInfo.theme,
      '--theme-color-opacity': systemInfo.theme + '25',
    }"
  >
    <common-input
      v-if="isShowFilter"
      :placeholder="searchPlaceholder"
      prefix-icon="el-icon-search"
      v-model="filterValue"
      :verify="false"
    ></common-input>

    <div
      slot="group"
      class="tree-data-wrap"
      :class="{
        'no-search-tree-data': !isShowFilter,
        'is-request-style': isRequest,
      }"
    >
      <div class="tree-shade" v-if="isRequest"></div>
      <vue-easy-tree
        v-loading="treeLoading"
        class="tree mt20"
        height="calc(100vh - 315px)"
        :data="treeData"
        :node-key="nodeKey"
        :indent="indent"
        :lazy="lazy"
        :load="load"
        :highlight-current="highlightCurrent"
        :props="treeProp"
        :check-strictly="true"
        :check-on-click-node="true"
        :expand-on-click-node="expandOnClickNode"
        :default-expand-all="defaultExpandAll"
        :default-expanded-keys="defaultExpandedKeys"
        :current-node-key="currentNodeKey"
        :filter-node-method="filterNode"
        @node-click="handleNodeClick"
        @node-expand="handleNodeExpand"
        @node-collapse="handleNodeCollapse"
        ref="tree"
      >
        <div
          slot-scope="scope"
          style="
            width: calc(100% - 30px);
            height: 100%;
            display: flex;
            align-items: center;
          "
        >
          <slot :scope="scope" v-if="isSlot"></slot>

          <common-carousel-text
            v-else
            :content="scope.data.label"
            :font-size="14"
          >
          </common-carousel-text>
        </div>
      </vue-easy-tree>
    </div>
  </div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
  name: "index",
  props: {
    isRequest: {
      type: Boolean,
      default: false,
    }, //点击节点请求时加入遮罩防止连续点击发送请求
    treeLoading: {
      type: Boolean,
      default: false,
    },
    isShowFilter: {
      type: Boolean,
      default: true,
    }, // 是否带筛选
    searchPlaceholder: {
      type: String,
      default: "查询组件",
    }, // 筛选框默认提示
    treeData: {
      type: Array,
      default: () => [],
    },
    treeProp: {
      type: Object,
      default: () => ({}),
    },
    isSlot: {
      type: Boolean,
      default: false,
    }, // 是否自定义节点样式
    searchForChildren: {
      type: Boolean,
      default: false,
    }, // 筛选是否显示子节点数据
    highlightCurrent: {
      type: Boolean,
      default: true,
    }, // 是否高亮显示
    expandOnClickNode: {
      type: Boolean,
      default: false,
    }, // 是否在点击节点的时候展开或者收缩节点
    defaultExpandAll: {
      type: Boolean,
      default: true,
    }, // 是否默认展开所有节点
    defaultExpandedKeys: {
      type: Array,
      default: () => [],
    }, // 默认展开的节点的 key 的数组
    indent: {
      type: Number,
      default: 16,
    }, // 相邻级节点间的水平缩进，单位为像素
    lazy: {
      type: Boolean,
      default: false,
    }, // 懒加载
    currentNodeKey: String, // 当前选中的节点

    isShowIconForNoChild: {
      type: Boolean,
      default: false,
    }, // 是否需要展示无子节点的父节点的icon
    setNodeByKey: {
      type: String,
      default: null,
    }, // key值，用于获取树节点中某个属性，根据属性值判断是否需要展示icon，与isShowIconForNoChild同时使用
    nodeKey: {
      type: String,
      default: "id",
    },
    hiddenIndexIcon: {
      type: Number,
      default: null,
    }, // 指定层级隐藏icon

    specialUse: {
      type: String,
      default: null,
    }, //特殊业务场景时传值，进行特殊处理
  },
  data() {
    return {
      filterValue: "",
      parentData: [],
    };
  },
  computed: {
    ...mapGetters(["systemInfo"]),
  },
  watch: {
    filterValue(val) {
      this.$emit("getParentNodeData", val);
      this.$refs.tree.filter(val);
    },
    treeData: {
      handler: function (val) {
        if (val.length && this.setNodeByKey && this.isShowIconForNoChild) {
          this.$nextTick(() => {
            let that = this;
            let setNode = (data) => {
              if (data.length) {
                data.forEach((f) => {
                  let index = that.$refs.tree.getNode(f).level;
                  // // 将指定层级且该层级下无子级的icon去掉
                  if (
                    this.hiddenIndexIcon !== null &&
                    this.hiddenIndexIcon === index &&
                    (!f.children || !f.children.length)
                  ) {
                    that.$refs.tree.getNode(f).isLeaf = true;
                    that.$refs.tree.getNode(f).expanded = true;
                  } else if (
                    (!f.children || !f.children.length) &&
                    !f[this.setNodeByKey]
                  ) {
                    // 设置其它层无子集时也显示icon
                    that.$refs.tree.getNode(f).isLeaf = false;
                    that.$refs.tree.getNode(f).expanded = false;
                    if (this.specialUse === "API") {
                      if (f.type === "2") {
                        that.$refs.tree.getNode(f).isLeaf = true;
                        that.$refs.tree.getNode(f).expanded = true;
                      }
                    }
                  } else {
                    setNode(f.children);
                  }
                });
              }
            };
            setNode(val);
          });
        }
      },
      deep: true,
      immediate: true,
    },
    currentNodeKey: {
      handler: function (val) {
        this.$nextTick(() => {
          this.$refs.tree.setCurrentKey(val);
        });
      },
    },
  },
  methods: {
    /**
     * 过滤
     * @param value
     * @param data
     * @param node
     * @returns {*|boolean|boolean}
     */
    filterNode(value, data, node) {
      let key = this.treeProp?.label || "label";

      // 如果什么都没填就直接返回
      if (!value) {
        return true;
      }
      // 如果传入的value和data中的label相同说明是匹配到了
      if (
        data[key] &&
        data[key]?.toLowerCase().indexOf(value?.toLowerCase()) !== -1
      ) {
        if (this.specialUse === "API") {
          if (data.type === "2") {
            return false;
          }
          if (data.type === "1") {
            this.$nextTick(() => {
              node.expanded = false;
            });
          }
          return true;
        } else {
          return true;
        }
      } else if (
        data.name &&
        data.name?.toLowerCase().indexOf(value?.toLowerCase()) !== -1
      ) {
        return true;
      }

      // 是否显示筛选节点的子节点
      if (this.searchForChildren) {
        return this.checkBelongToChooseNode(value, data, node);
      }
    },

    /**
     * 判断传入的节点是不是选中节点的子节点
     * @param value
     * @param data
     * @param node
     * @returns {boolean}
     */
    checkBelongToChooseNode(value, data, node) {
      let key = this.treeProp?.label || "label";
      const level = node.level;
      // 如果传入的节点本身就是一级节点就不用校验了
      if (level === 1) {
        return false;
      }
      // 先取当前节点的父节点
      let parentData = node.parent;
      // 遍历当前节点的父节点
      let index = 0;
      while (index < level - 1) {
        // 如果匹配到直接返回
        if (
          parentData.data[key] &&
          parentData.data[key]?.toLowerCase().indexOf(value?.toLowerCase()) !==
            -1
        ) {
          return true;
        } else if (
          parentData.data.name &&
          parentData.data.name?.toLowerCase().indexOf(value?.toLowerCase()) !==
            -1
        ) {
          return true;
        }
        // 否则的话再往上一层做匹配
        parentData = parentData.parent;
        index++;
      }
      // 没匹配到返回false
      return false;
    },
    /**
     * 节点点击事件
     * @param node
     * @param data
     */
    handleNodeClick(data, node) {
      // console.log(node)
      // console.log({data,node})
      this.$emit("handleNodeClick", { data, node });
    },

    /**
     * 获取树组件所有展开的节点id
     * @returns {Array}
     */
    getAllExpandedNodeIds() {
      let ids = [];
      for (let i = 0; i < this.$refs.tree.store._getAllNodes().length; i++) {
        if (
          this.$refs.tree.store._getAllNodes()[i].expanded &&
          !this.$refs.tree.store._getAllNodes()[i].isLeaf
        ) {
          ids.push(this.$refs.tree.store._getAllNodes()[i].data.id);
        }
      }
      return ids;
    },
    /**
     * 树节点展开时触发事件
     */
    handleNodeExpand(data, node) {
      this.$emit("handleNodeExpand", { data, node });
    },
    /**
     * 树节点关闭时触发事件
     */
    handleNodeCollapse(data, node) {
      this.$emit("handleNodeCollapse", { data, node });
    },

    load(node, resolve) {
      this.$emit("load", node, resolve);
    },
  },
  mounted() {},
};
</script>

<style scoped lang="scss">
.common-tree-wrap {
  width: 100%;
  height: 100%;
  overflow: hidden;

  .tree-data-wrap {
    margin-top: 12px !important;
    max-height: calc(100% - 44px) !important;
    overflow-y: scroll;
    overflow-x: hidden;
    position: relative;
    opacity: 1;
    .tree {
      ::v-deep .vue-recycle-scroller {
        padding-right: 3px;
      }
    }
    .tree-shade {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      background-color: var(--theme-color) !important;
      opacity: 0;
      z-index: 10;
    }

    ::v-deep .el-tree-node__content:hover {
      background-color: var(--theme-color-opacity) !important;
      color: var(--theme-color);
      /*border-radius: 3px;*/
    }

    ::v-deep
      .el-tree--highlight-current
      .el-tree-node.is-current
      > .el-tree-node__content {
      background-color: var(--theme-color-opacity);
      color: var(--theme-color) !important;
      /*border-radius: 3px;*/
    }

    ::v-deep .el-tree-node:focus > .el-tree-node__content {
      background-color: var(--theme-color-opacity);
      color: var(--theme-color);
    }

    ::v-deep .el-tree-node__content:hover {
      background-color: var(--theme-color-opacity);
      color: var(--theme-color);
    }
  }

  .no-search-tree-data {
    margin-top: 0 !important;
    max-height: 100% !important;
  }

  .is-request-style {
    opacity: 0.8;
    cursor: not-allowed;
  }
}
</style>
